﻿using System;
using System.Globalization;
using System.Runtime.Serialization;
using System.Text;


namespace Northwind.NET.Security
{

    [DataContract]
    public struct SecureString :
        IComparable<SecureString>, IEquatable<SecureString>
    {
        public static int Compare(SecureString strA, SecureString strB)
        {
            return String.Compare(strA.Value, strB.Value);
        }

    
        public static SecureString Concat(SecureString str0, SecureString str1)
        {
            return new SecureString(String.Concat(str0.Value, str1.Value));
        }

        public static SecureString operator +(
            SecureString str0,
            SecureString str1)
        {
            return new SecureString(String.Concat(str0.Value, str1.Value));
        }

        public static SecureString Concat(params SecureString[] values)
        {
            if (values == null)
            {
                throw new ArgumentNullException("values");
            }

            var securityHandle = SecurityHandle.Uncontrolled;
            var stringValues = new string[values.Length];
            return new SecureString(
                securityHandle,
                String.Concat(stringValues));
        }

        public static bool Equals(SecureString a, SecureString b)
        {
            return String.Equals(a.Value, b.Value);
        }

        public static bool Equals(
            SecureString a,
            SecureString b,
            StringComparison comparisonType)
        {
            return String.Equals(a.Value, b.Value, comparisonType);
        }

        public static implicit operator SecureString(string value)
        {
            return new SecureString(value);
        }

        public static bool IsEqual(SecureString a, SecureString b)
        {
            return String.Equals(a.Value, b.Value);
        }

        public static bool operator ==(SecureString a, SecureString b)
        {
            return String.Equals(a.Value, b.Value);
        }

        public static bool IsNullOrEmpty(SecureString value)
        {
            return value.value == null;
        }

        public static bool IsUnequal(SecureString a, SecureString b)
        {
            return !String.Equals(a.Value, b.Value);
        }

        public static bool operator !=(SecureString a, SecureString b)
        {
            return !String.Equals(a.Value, b.Value);
        }
        public static SecureString Parse(string valueString)
        {
            if (valueString == null)
            {
                throw new ArgumentNullException("valueString");
            }

            int i = valueString.IndexOf(';');

            if (i == -1)
            {
                throw new FormatException();
            }

            return new SecureString(
                new SecurityHandle(valueString.Substring(0, i)),
                valueString.Substring(i + 1));
        }

        public static string ToString(SecureString value)
        {
            return value.Value;
        }

        public static explicit operator string(SecureString value)
        {
            return value.Value;
        }

     
        private SecurityHandle securityHandle;
        private string value;

        public int Length
        {
            get
            {
                return value.Length;
            }
        }

        [DataMember(EmitDefaultValue = false, Order = 0)]
        public SecurityHandle SecurityHandle
        {
            get
            {
                return securityHandle;
            }

            private set
            {
                securityHandle = value;
            }
        }

        [DataMember(Order = 1)]
        public string Value
        {
            get
            {
                return value ?? "";
            }

            private set
            {
                this.value = value != null && value.Length == 0 ? null : value;
            }
        }

        public SecureString(string value)
            : this(SecurityHandle.Uncontrolled, value)
        {
        }

        public SecureString(
            SecurityHandle securityHandle,
            string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            this.securityHandle = securityHandle;
            this.value = value.Length == 0 ? null : value;
        }
        public override bool Equals(object obj)
        {
            return Value.Equals(obj as string);
        }

        public bool Equals(SecureString value)
        {
            return Value.Equals(value.Value);
        }

        public bool Equals(SecureString value, StringComparison comparisonType)
        {
            return Value.Equals(value.Value, comparisonType);
        }

        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }


		#region IComparable<SecureString> Members

		public int CompareTo(SecureString other)
		{
			return Value.CompareTo(other.Value);
		}

		#endregion
	}
}